package com.hzw.code.vm

import android.os.Bundle
import android.view.View
import androidx.fragment.app.Fragment
import androidx.lifecycle.Observer
import androidx.lifecycle.ViewModelProvider
import com.hzw.code.R
import com.hzw.code.annotation.BindViewModel
import com.hzw.code.pageState.OnRetryListener
import com.hzw.code.pageState.OnShowHideViewListener
import com.hzw.code.pageState.PageStateManager
import com.hzw.code.pageState.State
import com.hzw.code.vm.event.Event
import com.scwang.smartrefresh.layout.listener.OnRefreshListener
import kotlinx.android.synthetic.main.page_layout.*

/**
 *
 * @Author:         HuaZhongWei
 * @CreateDate:     2020/4/20 16:00
 *
 * @Description:    基类Fragment
 *
 */
abstract class PageFragment : Fragment(R.layout.page_layout), IView {

    var pageStateManager: PageStateManager? = null

    open val isNeedPageStateManager: Boolean = true

    var isNeedRefreshOnResume = false

    var isFirstVisible = true

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        initTitle()
        if (isNeedPageStateManager) {
            initContent()
        } else {
            contentContainer.addView(View.inflate(requireContext(), getLayoutResId(), null))
        }
        initViewModel()
        init(savedInstanceState)
    }

    override fun onResume() {
        super.onResume()
        if (isFirstVisible) {
            onFirstVisible()
            isFirstVisible = false
        }

        if (isNeedRefreshOnResume) {
            onResumeRefresh()
            isNeedRefreshOnResume = false
        }
    }

    override fun onDestroy() {
        super.onDestroy()
        isFirstVisible = true
        isNeedRefreshOnResume = false
    }

    open fun onResumeRefresh() {

    }

    open fun onFirstVisible() {

    }

    private fun initTitle() {
        val titleLayout = initTitleLayout()
        if (titleLayout != null) {
            titleContainer.visibility = View.VISIBLE
            titleContainer.addView(titleLayout.rootLayout)
        } else {
            titleContainer.visibility = View.GONE
        }
    }

    private fun initContent() {
        pageStateManager = initPageStateManager() ?: PageStateManager.Builder(requireContext())
            .loadingLayoutResId()
            .contentLayoutResId(getLayoutResId())
            .errorView(
                onRefreshListener = OnRefreshListener { onRefreshForError(it) },
                onRetryListener = object : OnRetryListener {
                    override fun onRetry() {
                        onRetryForError()
                    }
                }
            )
            .emptyView(
                onRefreshListener = OnRefreshListener {
                    onRefreshForEmpty(it)
                },
                onRetryListener = object : OnRetryListener {
                    override fun onRetry() {
                        onRetryForEmpty()
                    }
                }
            )
            .netErrorView(
                onRefreshListener = OnRefreshListener { onRefreshForNetError(it) },
                onRetryListener = object : OnRetryListener {
                    override fun onRetry() {
                        onRetryForNetError()
                    }
                }
            )
            .onShowHideViewListener(object : OnShowHideViewListener {
                override fun onShowView(view: View, state: State) {
                    onShowViewForPage(view, state)
                }

                override fun onHideView(view: View, state: State) {
                    onHideViewForPage(view, state)
                }
            })
            .build()

        contentContainer.addView(pageStateManager?.rootLayout)
    }

    open fun initPageStateManager(): PageStateManager? {
        return null
    }

    open fun initTitleLayout(): TitleLayout? {
        return null
    }

    private fun initViewModel() {
        javaClass.declaredFields
            .filter { field ->
                field.isAnnotationPresent(BindViewModel::class.java)
            }
            .forEach { field ->
                val viewModel: AbsViewModel = ViewModelProvider(this).get(
                    field.getAnnotation(
                        BindViewModel::class.java
                    )!!.model.java
                )
                initCommonEvent(viewModel)
                field.set(this, viewModel)
            }
    }

    private fun initCommonEvent(viewModel: AbsViewModel) {
        viewModel.eventLiveData.observe(viewLifecycleOwner, Observer { commonEvent ->
            when (commonEvent.event) {
                Event.SHOW_LOADING -> showLoading()
                Event.HIDE_LOADING -> hideLoading()
                Event.CONTENT -> showContent()
                Event.ERROR -> showError()
                Event.NET_ERROR -> showNetError()
                Event.EMPTY -> showEmpty()
                Event.TOAST -> showToast(commonEvent.msg)
            }
        })
    }

    override fun showLoading() {
        pageStateManager?.showLoading()
    }

    override fun hideLoading() {
        pageStateManager?.hideLoading()
    }

    override fun showContent() {
        pageStateManager?.showContentView()
    }

    override fun showError() {
        pageStateManager?.showErrorView()
    }

    override fun showNetError() {
        pageStateManager?.showNetErrorView()
    }

    override fun showEmpty() {
        pageStateManager?.showEmptyView()
    }

    abstract fun getLayoutResId(): Int

    abstract fun init(savedInstanceState: Bundle?)
}